package com.yami.shop.delivery.multishop.listener;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.bean.app.dto.ShopCartItemDto;
import com.yami.shop.bean.enums.DeliveryType;
import com.yami.shop.bean.enums.OrderStatus;
import com.yami.shop.bean.event.OrderChangeAddrEvent;
import com.yami.shop.bean.model.Order;
import com.yami.shop.bean.model.OrderItem;
import com.yami.shop.bean.model.Product;
import com.yami.shop.bean.model.UserAddr;
import com.yami.shop.bean.param.OrderChangeAddrParam;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.Arith;
import com.yami.shop.delivery.common.service.SameCityService;
import com.yami.shop.delivery.common.service.TransportManagerService;
import com.yami.shop.service.OrderItemService;
import com.yami.shop.service.OrderService;
import com.yami.shop.service.ProductService;
import lombok.AllArgsConstructor;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 商家修改订单地址事件
 * @author Citrus
 * @date 2021/11/25 11:05
 */
@Component("orderChangeAddrListener")
@AllArgsConstructor
public class OrderChangeAddrListener {

    private final TransportManagerService transportManagerService;
    private final SameCityService sameCityService;
    private final OrderService orderService;
    private final OrderItemService orderItemService;
    private final ProductService productService;

    @EventListener(OrderChangeAddrEvent.class)
    public void calculateChangeAddrTransFee(OrderChangeAddrEvent event) {
        OrderChangeAddrParam order = event.getOrder();
        Order orderDb = orderService.getOne(new LambdaQueryWrapper<Order>()
                .eq(Order::getOrderId, order.getOrderId())
                .eq(Order::getOrderNumber, order.getOrderNumber())
        );
        if (orderDb.getStatus() > OrderStatus.PADYED.value() && !Objects.equals(orderDb.getStatus(), OrderStatus.WAIT_GROUP.value())) {
            // 订单状态异常，无法更改订单地址
            throw new YamiShopBindException("yami.order.status.error");
        }
        List<OrderItem> orderItems = orderItemService.list(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderNumber, order.getOrderNumber()));
        List<Long> prodIds = orderItems.stream().map(OrderItem::getProdId).collect(Collectors.toList());
        Map<Long, Product> prodMap = productService.getProdDeliveryTemplateIdByProdIds(prodIds);
        double freightAmount = orderDb.getFreightAmount();
        Double resAmount  = 0.0;
        List<ShopCartItemDto> productItems = new ArrayList<>();
        for (OrderItem orderItem : orderItems) {
            Product prod = prodMap.get(orderItem.getProdId());
            ShopCartItemDto productItem = new ShopCartItemDto();
            productItem.setShopId(orderItem.getShopId());
            productItem.setProdId(orderItem.getProdId());
            productItem.setSkuId(orderItem.getSkuId());
            productItem.setProdCount(orderItem.getProdCount());
            productItem.setProductTotalAmount(orderItem.getProductTotalAmount());
            productItem.setDeliveryTemplateId(prod.getDeliveryTemplateId());
            productItem.setDeliveryAmount(prod.getDeliveryAmount());
            productItems.add(productItem);
        }
        UserAddr userAddr = new UserAddr();
        if (Objects.equals(orderDb.getDvyType(), DeliveryType.SAME_CITY.getValue())) {
            // 同城配送
            userAddr.setLat(order.getLat());
            userAddr.setLng(order.getLng());
            resAmount = sameCityService.calculateTransFee(productItems, userAddr);
            if (resAmount == -2.0) {
                // 当前店铺未开启同城配送!
                throw new YamiShopBindException("yami.order.same.city.error");
            } else if (resAmount == -1.0) {
                // 超出当前设置的配送距离!
                throw new YamiShopBindException("yami.order.same.city.error4");
            }
        } else {
            userAddr.setAreaId(order.getAreaId());
            resAmount = transportManagerService.calculateTransFee(productItems, userAddr, null);
        }
        double changeAmount = Arith.sub(resAmount, freightAmount);
        event.setChangeAmount(changeAmount);
    }
}
